/**
 * 用法 <input name="id" placeholder = "试试" allow="notnull" must="true/false 缺省为true"/>
 * ps:input的父级节点为相对对位 name,allow 两个个属性石必须的。
 *  allow的值目前支持： 多个检验用;号隔开，提示信息里不要出现;号，
 *  1 ：notnull 校验不全是空格 
 *  2 ：email 邮箱 
 *  3 ：eng 英文 
 *  4 ：reg 自定义正则 格式为 allow ="reg:正则表达式&&提示内容"，自定义正则不需要写前后的斜杠，直接写，第二个是提示信息 
 *  5 ：between between:1,2&&提心信息 1 2 为值域
 *  6 ：eq eq:需要比较的name&&提示信息 
 *  7 ：ajax allow=“ajax:url&&提示信息”
 *  8 : length   allow = length :min,max&&提示信息 直接一个默认最大长度 length:max&&提示信息
 *   可以扩展、
 *   其中设置  提交事件的按钮 只需要 给 该dom 加上 submit_btn  class
 *   
 *   checkForm("formid"); 即可
 */
(function($) {
	"use strict";
	/**
	 * 默认的正则
	 */
	var regulars = {
		"email" : [
				/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/,
				"格式不对" ],
		"eng" : [ /^[A-Za-z]+$/, "只能输入英文" ],
		"chn" : [ /^[\u0391-\uFFE5]+$/, "只能输入汉字" ],
		"mobile" : [ /^1\d{10}$/, "手机格式错误" ],
		"notnull" : [ /^[\s\S]{1,200}$/, "不能为空,且长度小于200" ],
		"int" : [ /^-?\d+$/, "只能整数" ],
		"double" : [ /^(-?\d+)(\.\d+)?/, "只能输入数字" ],
		"identity" : [/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,"身份证号码格式不正确"]
	};

	/**
	 * 样式集合
	 */
	var cssClass = {
		outer_div_focus : "outer_div_focus",
		err_inner_div : "err_inner_div",
		right_inner_div : "right_inner_div",
		ajax_inner_div : "ajax_inner_div",
		tip_top_div : "tip_top_div",
		tip_bottom_div : "tip_bottom_div"
	};

	var placeholderSupport = 'placeholder' in document.createElement('input');// 检查浏览器是不是支持placeholder
	/**
	 * 浮动块对象
	 */
	var floatTip = new FloatTip();

	if (!Function.prototype.bind) {//让不兼容bind方法兼容bind
		Function.prototype.bind = function(oThis) {
			if (typeof this !== "function") {
				throw new TypeError(
						"Function.prototype.bind - what is trying to be bound is not callable");
			}
			var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {
			}, fBound = function() {
				return fToBind.apply(this instanceof fNOP && oThis ? this
						: oThis, aArgs.concat(Array.prototype.slice
						.call(arguments)));
			};

			fNOP.prototype = this.prototype;
			fBound.prototype = new fNOP();

			return fBound;
		};
	}
	;

	/**
	 * 检验的所有方法 集合
	 */
	var checkFuncs = {

		/**
		 * 按正则检验
		 * 
		 * @param reg
		 * @param isCustomed
		 */
		checkByReg : function(reg, isCustomed) {
			if (arguments.length == 3) {
				reg = reg.split("&&");
				reg[0] = new RegExp(reg[0]);
			}
			var val = $(this).val();

			var result = reg[0].test(val);
			if (!result) {
				this.hasValidated = false;
			} else {
				this.hasValidated = true;
			}
			blurFunc.call(this, result, reg[1]);

		},
		/**
		 * 检查相等
		 * 
		 * @param res
		 */
		checkByEq : function(res) {
			res = res.split("&&");
			var val = $(this).parents("form").find("[name='" + res[0] + "']")
					.val();
			if (!val) {
				blurFunc.call(this, null, null, true);
				return;
			}
			var result = val == $(this).val();
			if (!result) {
				this.hasValidated = false;
			} else {
				this.hasValidated = true;
			}
			blurFunc.call(this, result, res[1]);
		},
		/**
		 * AJax检验
		 * 
		 * @param url
		 */
		checkByAjax : function(info) {
			info = info.split(";");
			var val = $(this).val();
			if(info.length == 2){
				var regs = info[0].split("&&");
				var reg = regs[0];
				var tip = regs[1];
				if(regulars[reg]){
					if(!tip) tip = regulars[reg][1];
					reg = regulars[reg][0];
				}else{
					reg = new RegExp(reg);
				}
				var result = reg.test(val);
				if(!result){
					this.hasValidated = false ; 
					blurFunc.call(this, result, tip);
					return ;
				}
			}
			info = info[info.length - 1];
			info = info.split("&&");
			var url = info[0], msg = info[1];
			var siblings = $(this).next();
			siblings.removeClass(cssClass.err_inner_div + " "
					+ cssClass.right_inner_div);
			siblings.addClass(cssClass.ajax_inner_div);
			$.ajax({
				url : url,
				type : "post",
				data : $(this).attr("name") + "=" + val,
				dataType : "json",
				async : true,
				success : function(d) {
					if (d == 1) {
						this.hasValidated = true;
					} else {
						this.hasValidated = false;
					}
					blurFunc.call(this, this.hasValidated, msg);
				}.bind(this),
				error : function() {
					this.hasValidated = false;
					blurFunc.call(this, this.hasValidated, "网络出错");
				}.bind(this)
			});
		},
		checkByLength : function(str) {
			var reg = str.split("&&");
			var rules = reg[0];
			rules = rules.split(",");
			var min = 0,max = null;
			if (rules.length = 2) {
				min = parseInt(rules[0],10);
				max = parseInt(rules[1],10);
			}else{
				max = parseInt(rules[0],10);
			}
			var tip = reg[1];
			var val = $(this).val();
			if(val.length<min || val.length > max){
				this.hasValidated = false;
			}else{
				this.hasValidated = true;
			}
			blurFunc.call(this, this.hasValidated, tip);
		}

	};

	/**
	 * checkForm方法 会自动初始化样式
	 */
	function checkForm(id) {
		var parent = $("#" + id);
		/**
		 * 提交时检验事件
		 */
		$(parent).submit(function(e) {
			var children = $("input[type=text]", parent);
			for ( var i = 0, len = children.length; i < len; i++) {
				var input = children[i];
				if ($(input).css("display") != "none") {
					if (!input.hasValidated) {
						e.preventDefault();// 阻止提交表单
						return false;
					}
				}
			}
			floatTip.destory();
			floatTip = null;
		});
		/**
		 * 给拥有 class submit_btn 设置点击 提交form事件
		 */
		$(".submit_btn", parent).bind("click.form", function() {
			$(parent).submit();
		});

		/**
		 * 初始化每个看得见input样式
		 */
		$("input[type=text]", parent).each(
				function() {
					var input = this;
					if ($(input).css("display") != "none") {
						$(input).wrap("<div class='outer_div'/>").parent()
								.append($("<div class='inner_div'/>"));
						$(input).addClass("input_dom");
						var allow = $(input).attr("allow");
						if(!allow) return;
						if (!placeholderSupport) {
							var txt = $(this).attr("placeholder");
							if (txt) {
								this.holder = $('<span></span>').text(txt).css(
										{
											position : "absolute",
											left : 0,
											top : "6px",
											color : "rgb(169,187,177)"
										}).appendTo($(this).parent());
								this.holder.click(function(e) {
									this.holder.hide();
									this.focus();
								}.bind(this));
							}
						}
						var must = $(input).attr("must");
						input.hasValidated = must == "true" ? false : true;// 不写must
						// 默认为必填项
						var allowarr = allow.split(":");
						var defaultreg = regulars[allowarr[0]];// 查看是否是默认正则
						var checkfunc = null;
						if (defaultreg) {
							checkfunc = checkFuncs.checkByReg.bind(input,
									defaultreg);
						} else {
							checkfunc = checkFuncs["checkBy"
									+ firstUpcase(allowarr[0])].bind(input,
									allowarr[1], true);
						}
						$(input).bind("blur.form", function() {
							var must = $(this).attr("must");
							if (must == "false") {
								var val = $(this).val();// 非必填项在有内容时才检验
								if (!val)
									return;
							}
							checkfunc();
						});
						$(input).bind("focus.form", focusFunc.bind(input));
					}

				});

	}

	/**
	 * 首字母大写。
	 */
	function firstUpcase(str) {
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}
	/**
	 * 获取焦点样式变化
	 */
	function focusFunc() {
		if (this.holder)
			this.holder.hide();
		floatTip.hidden(this);
		$(this.parentNode).css("border", "1px solid rgb(74,145,255)");

	}

	/**
	 * 失去焦点时样式转变 result 验证结果，msg 提示消息 isdefault 是否转到默认状态
	 */
	function blurFunc(result, msg, isdefault) {
		if (!$(this).val() && this.holder) {
			this.holder.show();
		}
		var siblings = $(this).next();
		siblings.removeClass(cssClass.ajax_inner_div);
		if (isdefault) {
			$(this.parentNode).css("border", "1px solid rgb(169, 169, 169)");
			return;
		}
		if (result) {
			siblings.removeClass(cssClass.err_inner_div);
			siblings.addClass(cssClass.right_inner_div);
			$(this.parentNode).css("border", "1px solid rgb(147,191,100)");
			floatTip.hidden(this);
		} else {
			siblings.removeClass(cssClass.right_inner_div);
			siblings.addClass(cssClass.err_inner_div);
			$(this.parentNode).css("border", "1px solid rgb(241,151,133)");
			floatTip.show(this, msg);
		}
	}

	/**
	 * 浮动框对象
	 */
	function FloatTip() {
		this.bodyDiv = $("<div/>").appendTo(document.body).css({
			position : "absolute",
			display : "none"
		});
		;
		this.topDiv = $("<div/>").appendTo(this.bodyDiv).addClass(
				cssClass.tip_top_div);
		this.bottomDiv = $("<div/>").appendTo(this.bodyDiv).addClass(
				cssClass.tip_bottom_div);
	}

	/**
	 * 显示
	 * 
	 * @param input
	 *            input对象
	 * @param msg
	 *            提示信息
	 */
	FloatTip.prototype.show = function(input, msg) {
		this.input = input;
		var parent = $(input.parentNode);
		if (!msg)
			return;
		this.topDiv.text(msg);
		var offset = parent.offset();
		this.bodyDiv.css({
			display : ""
		});
		var width = this.topDiv.width();
		var pWidth = parent.width();
		var left = pWidth / 2 - width / 2 + offset.left - 10;
		var top = offset.top - 40;
		this.bodyDiv.css({
			top : top + "px",
			left : left + "px",
		});
		this.bottomDiv.css({
			left : (width / 2 - 5) + "px"
		});

	};
	/**
	 * 隐藏
	 */
	FloatTip.prototype.hidden = function(input) {
		if(this.input == input){
			this.bodyDiv.css({
				display : "none"
			});
		}
	};

	/**
	 * 摧毁
	 */
	FloatTip.prototype.destory = function() {
		this.bodyDiv.remove();
		this.bodyDiv = null;
		this.topDiv = null;
		this.bottomDiv = null;
		this.input = null;
	};

	window["checkForm"] = checkForm;
})(jQuery);